#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>


//线程互斥锁 
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

//工人的数量
#define MAXTHREADS 5

//号码牌的个数 
#define MAXNUM 1000000 

//号码牌 
int buf[MAXNUM];

//号码牌的编号 ---》下标 
int num = 0;
int Num = 0;

//号码牌上的值val应该要与号码牌的编号（下标）相等 
//意思就是编号为0的号码牌上应该要写0 
//编号为num的号码排上面要写val 即buf[num]=val ; //buf[i] = i;
int val = 0;

//工人 --- 生产者
void *produce(void *arg)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        if(num >= MAXNUM)//号码牌写完了 工人完成任务了 线程结束
        {
            pthread_mutex_unlock(&mutex);
            return NULL;
        }
        buf[num] = val; 
        num++;
        val++;
        //计算自己写了多少个的值 要加1 
        *( (int *)(arg) ) += 1;
		if (num > Num)
		{
			pthread_cond_signal(&cond);
		}
        pthread_mutex_unlock(&mutex);

    }

}


//经理 --- 消费者 
void *consume (void *arg)
{
    for(Num = 0; Num < MAXNUM; Num++)
    {
        
    	while(1)
        {   
            pthread_mutex_lock(&mutex);
            if(Num < num)
            {
                pthread_mutex_unlock(&mutex);
                break;
            }
			pthread_cond_wait(&cond, &mutex);
        }

        if(buf[Num] != Num)
        {
            printf("buf[%d] = %d\n", Num , buf[Num]);
        }
    }

    return NULL;

}
int main()
{
    //定义一个数组 用来保存5个线程的id 
    pthread_t tids[MAXTHREADS];

    //用来计算每个工人写号码牌的个数
    int count[MAXTHREADS]={0};

    //招5个工人去写号码牌 
    int i; 
    for(i=0;i<MAXTHREADS;i++)
    {
        pthread_create(&tids[i]  ,NULL , produce ,   (void *)( &count[i]) );
    }

    //招一个经理去检查 
    pthread_t tid;
    pthread_create(&tid , NULL , consume ,NULL);

    int sum = 0;
    //等待生产者线程和消费者线程结束 并回收资源
    for(i=0;i<5;i++)
    {
        pthread_join(tids[i],NULL);
        printf("count[%d] = %d\n", i , count[i]);
        sum += count[i];
    }
    pthread_join(tid,NULL);
    printf("sum = %d\n",sum);
	
	pthread_mutex_destroy(&mutex);	
	pthread_cond_destroy(&cond);	
	exit(0);
}












